import { AppDataSource, CrawlerTask, CrawledData, CrawlerResult } from '@weubi/shared';
import { Repository } from 'typeorm';
import { EngineFactory } from '../engines/EngineFactory';
import { DataProcessor } from '../processors/DataProcessor';
import { logger } from '../utils/logger';

export class CrawlerService {
  private taskRepository: Repository<CrawlerTask>;
  private dataRepository: Repository<CrawledData>;
  private engineFactory: EngineFactory;
  private dataProcessor: DataProcessor;
  private isInitialized = false;

  constructor() {
    this.taskRepository = AppDataSource.getRepository(CrawlerTask);
    this.dataRepository = AppDataSource.getRepository(CrawledData);
    this.engineFactory = new EngineFactory();
    this.dataProcessor = new DataProcessor();
  }

  async initialize(): Promise<void> {
    if (this.isInitialized) return;

    try {
      // 初始化引擎工厂
      await this.engineFactory.initialize();
      
      // 初始化数据处理器
      await this.dataProcessor.initialize();

      this.isInitialized = true;
      logger.info('✅ Crawler service initialized successfully');
    } catch (error) {
      logger.error('❌ Failed to initialize crawler service:', error);
      throw error;
    }
  }

  async executeCrawlerTask(taskId: string): Promise<CrawlerResult> {
    logger.info(`🕷️ Starting crawler task: ${taskId}`);

    try {
      // 获取任务信息
      const task = await this.taskRepository.findOne({
        where: { id: taskId },
      });

      if (!task) {
        throw new Error(`Task not found: ${taskId}`);
      }

      if (!task.canRun) {
        throw new Error(`Task cannot be run in current state: ${task.status}`);
      }

      // 更新任务状态为运行中
      task.markAsRunning();
      await this.taskRepository.save(task);

      // 获取爬虫引擎
      const engine = await this.engineFactory.getEngine(task.engine);
      
      // 执行爬虫任务
      const result = await engine.execute(task);

      if (result.success && result.data) {
        // 处理爬取的数据
        const processedData = await this.dataProcessor.processData(result.data, task.url);
        
        // 保存数据到数据库
        await this.saveData(task, processedData, result);

        // 更新任务状态为完成
        task.markAsCompleted(result);
        await this.taskRepository.save(task);

        logger.info(`✅ Crawler task completed: ${taskId}`);
      } else {
        // 任务失败
        const errorMessage = result.error || 'Unknown error';
        task.markAsFailed(errorMessage);
        await this.taskRepository.save(task);

        logger.error(`❌ Crawler task failed: ${taskId} - ${errorMessage}`);
      }

      return result;

    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown error';
      logger.error(`❌ Crawler task error: ${taskId} - ${errorMessage}`);

      // 更新任务状态为失败
      let taskUrl = 'unknown';
      try {
        const task = await this.taskRepository.findOne({
          where: { id: taskId },
        });
        if (task) {
          taskUrl = task.url;
          task.markAsFailed(errorMessage);
          await this.taskRepository.save(task);
        }
      } catch (updateError) {
        logger.error('❌ Failed to update task status:', updateError);
      }

      return {
        success: false,
        error: errorMessage,
        metadata: {
          engine: 'http' as const,
          timestamp: new Date(),
          url: taskUrl,
        },
      };
    }
  }

  async getAvailableEngines(): Promise<string[]> {
    return this.engineFactory.getAvailableEngines();
  }

  async getEngineStatus(): Promise<Record<string, boolean>> {
    const engines = this.engineFactory.getAvailableEngines();
    const status: Record<string, boolean> = {};

    for (const engineName of engines) {
      try {
        const engine = await this.engineFactory.getEngine(engineName);
        status[engineName] = await engine.isAvailable();
      } catch (error) {
        status[engineName] = false;
      }
    }

    return status;
  }

  async cleanup(): Promise<void> {
    try {
      await this.engineFactory.cleanup();
      // DataProcessor doesn't need cleanup
      logger.info('✅ Crawler service cleaned up');
    } catch (error) {
      logger.error('❌ Error during crawler service cleanup:', error);
    }
  }

  private async saveData(
    task: CrawlerTask,
    processedData: any,
    result: CrawlerResult
  ): Promise<void> {
    try {
      // 生成数据哈希用于去重
      const hash = CrawledData.generateHash(processedData, task.url);

      // 检查是否已存在相同数据
      const existingData = await this.dataRepository.findOne({
        where: { hash },
      });

      if (existingData) {
        logger.warn(`⚠️ Duplicate data detected for task ${task.id}, skipping save`);
        return;
      }

      // 创建新的数据记录
      const crawledData = this.dataRepository.create({
        taskId: task.id,
        url: task.url,
        data: processedData,
        hash,
        engine: task.engine,
        statusCode: result.metadata.statusCode,
        responseTime: result.metadata.duration,
        dataSize: JSON.stringify(processedData).length,
        metadata: {
          userAgent: task.config.userAgent,
          ...result.metadata,
        },
        isValid: true,
        isProcessed: false,
      });

      await this.dataRepository.save(crawledData);
      logger.info(`💾 Data saved for task ${task.id}: ${crawledData.id}`);

    } catch (error) {
      logger.error(`❌ Failed to save data for task ${task.id}:`, error);
      throw error;
    }
  }

  // 获取任务统计信息
  async getTaskStats(): Promise<any> {
    const total = await this.taskRepository.count();
    const running = await this.taskRepository.count({
      where: { status: 'running' },
    });
    const completed = await this.taskRepository.count({
      where: { status: 'completed' },
    });
    const failed = await this.taskRepository.count({
      where: { status: 'failed' },
    });

    return {
      total,
      running,
      completed,
      failed,
      pending: total - running - completed - failed,
    };
  }
}
